package com.loeng.module.system.service.tenant;

import com.loeng.framework.tenant.core.config.TenantProperties;
import com.loeng.framework.tenant.core.context.TenantContextHolder;
import com.loeng.module.system.dal.dataobject.permission.MenuDO;
import com.loeng.module.system.dal.dataobject.tenant.TenantDO;
import com.loeng.module.system.dal.mysql.tenant.TenantMapper;
import com.loeng.module.system.service.permission.MenuService;
import com.loeng.module.system.service.tenant.handler.TenantMenuHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Objects;
import java.util.Set;

import static com.loeng.framework.common.util.collection.CollectionUtils.convertSet;

/**
 * 租户 Service 实现类
 * @author loeng zhuo
 */
@Service
public class TenantServiceImpl implements TenantService {

    @Resource
    private TenantMapper tenantMapper;

    /**
     * 由于 loeng.tenant.enable 配置项，可以关闭多租户的功能，所以这里只能不强制注入
     */
    @Autowired(required = false)
    private TenantProperties tenantProperties;

    @Resource
    private MenuService menuService;
    @Resource
    private TenantPackageService tenantPackageService;

    /**
     * 根据租户名，获得租户信息
     *
     * @param name 租户名
     * @return 租户信息
     */
    @Override
    public TenantDO getTenantByName(String name) {
        return tenantMapper.selectByName(name);
    }

    /**
     * 根据域名，获得租户信息
     *
     * @param website 域名
     * @return 租户信息
     */
    @Override
    public TenantDO getTenantByWebsite(String website) {
        return tenantMapper.selectByWebsite(website);
    }

    /**
     * 进行租户的菜单处理逻辑
     * 其中，租户编号从 {@link TenantContextHolder} 上下文中获取
     *
     * @param handler 处理器
     */
    @Override
    public void handleTenantMenu(TenantMenuHandler handler) {
        if (isTenantDisable()) {
            return ;
        }
        TenantDO tenant = getTenant(TenantContextHolder.getRequiredTenantId());
        // 判断是否为系统租户（系统租户具有全量菜单）
        Set<Long> menuIds;
        if (isSystemTenant(tenant)) {
            menuIds = convertSet(menuService.getMenuList(), MenuDO::getId);
        } else {
            menuIds = tenantPackageService.getTenantPackage(tenant.getPackageId()).getMenuIds();
        }
        // 执行处理器 (即Controller那里Lambda表达式 类似于匿名实现类)
        handler.handle(menuIds);
    }

    /**
     * 获得租户
     *
     * @param id 编号
     * @return 租户
     */
    @Override
    public TenantDO getTenant(Long id) {
        return tenantMapper.selectById(id);
    }

    /**
     * 判断租户是否禁用
     *
     * @return 是否禁用
     */
    private boolean isTenantDisable() {
        return tenantProperties == null || Boolean.FALSE.equals(tenantProperties.getEnable());
    }

    /**
     * 判断租户是否为系统租户
     *
     * @param tenant 租户
     * @return 是否为系统租户
     */
    private boolean isSystemTenant(TenantDO tenant) {
        return Objects.equals(tenant.getPackageId(), TenantDO.PACKAGE_ID_SYSTEM);
    }

}
